from helpFunc import *
import socket,select,os,time
from connbase import *
from streams import *
import json

class tcpRePeer(tcpReBase):
    def __init__(self,portNum,salt,rate,pushAhead,packLimit,savePath,debug):
        tcpReBase.__init__(self)     
        import threading    
        u = UStreamServer(portNum,salt,rate,pushAhead,packLimit,debug)        
        j = json.dumps(u.portList)
        f = open(savePath,'w')
        f.write(j)
        f.close()
        print ('save file ok'+savePath)
        t = threading.Thread(target=u.doWork)
        t.setDaemon(True)
        t.start()
        while True:
            try:
                so = socket.socket()
                add = ('127.0.0.1',u.listenPort)
                so.connect(add)    
                break
            except:
                pass        
        #serso = socket.socket()
        #add = ('0.0.0.0',9997)
        
        #serso.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        #serso.bind(add)
        #serso.listen(1)
        #so,b = serso.accept()
        #serso.close()
        print ('server starts')
        self.connSock=so
        so.setblocking(0)
        self.connectPollingMap = {}
        while True:
            self.dowork()
            
    def dowork(self):                      
        rl = [self.connSock]
        if len(self.peerBuf)<self.peerBufMax:
            rl += self.getReadSocks()
            
        wl = self.getWriteSocks()+list(self.connectPollingMap.keys())
        if self.peerBuf:
            wl.append(self.connSock)
            
        el = self.connectPollingMap.keys()
        rl,wl,el = select.select(rl,wl,el,1)
        
        for sock in rl:
            if sock == self.connSock:
                ss = sock.recv(con_recLen)                
                msgList = self.dealData(sock, ss)
                for one in msgList:
                    self.decodeMsg(one)                                   
                    if  self.decodeType==askConn_g:
                        print ('ask conn')
                        if self.connNum > self.maxNum:
                            print ('too much',self.connNum)
                            dd = self.makeMsg(connBack_g,self.decodeId,b'\x00')                          
                            self.sendMsg(dd)                              
                        try:
                            s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)                                                                                             
                            s.setblocking(0)
                            s.connect_ex(('127.0.0.1',8080))
                            self.connectPollingMap[s]={'id':self.decodeId}
                            
                        except Exception as e:
                            print (e)
                            s.close()
                            dd = self.makeMsg(connBack_g,self.decodeId,b'\x00')    
                            self.sendMsg(dd)    
                    else:
                        self.dealConnsockNormal(self.decodeId, self.decodeType,self.decodeData)
                continue
            self.dealProxysocks(sock)
        for sock in wl:
            if sock == self.connSock:
                n = self.connSock.send(self.peerBuf)
                self.peerBuf = self.peerBuf[n:]
                continue            
            if sock in self.connectPollingMap:
                id = self.connectPollingMap[sock]['id']
                del self.connectPollingMap[sock]
                dd = self.makeMsg(connBack_g,id,b'\x01')    
                self.sendMsg(dd)
                self.proxySocks[sock] = {'id':id,'data':b'','peerclose':False,
                                                                       'peerFull':False,'tellMyFull':False}
                self.idMap[id] = {'sock':sock}
                self.connNum +=1 
                print ('accept',self.connNum )
                continue
            self.dealWritesocks(sock)
    
        for sock in el:
            if sock in self.connectPollingMap:
                sock.close()
                id = self.connectPollingMap[sock]['id']
                del self.connectPollingMap[sock]                
                dd = self.makeMsg(connBack_g,id,b'\x00')      
                self.sendMsg(dd)                     

if __name__ == '__main__':
    import sys
    ar = sys.argv
    portNum = maxPortNum 
    rate = con_minRate
    pushAhead = con_pushAhead
    packLimit = con_packLimit
    salt = b'salt'
    savePath = 'a.txt'
    debug = True
    if len(ar)>1:
        s = ar[1].encode()
        import base64,json
        j = base64.b64decode(s)
        m = json.loads(j.decode())
        portNum =   m['num']
        rate = m['rate']
        pushAhead = m['pushAhead']
        packLimit = m['packLimit']
        salt = m['salt'].encode()
        savePath = m['savePath']
        debug = False
    t = tcpRePeer(portNum,salt,rate,pushAhead,packLimit,savePath,debug)  
    